#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@NAME          : mdact.py
@TIME          : 2024/12/05 20:33:45
@AUTHOR        : chenlip
@VERSION       : 0.0.1
@DESCRIPTION   : 单个markdown文件操作
'''
# --------------------------引用--------------------------
import os, sys, json, re

from .minioact import minioclient
# --------------------------引用--------------------------

class MdAct:
    def __init__(self, _mdfile:str):
        # md文件路径
        self.md_file = _mdfile
        # md文件内容
        self.md_cont = self.get_md_content()
        # md文件目录结构及内容
        self.md_toc_cont = self.get_md_toc_content()
        # md文件目录结构
        self.md_toc = self.get_md_toc()

    def get_md_content(self) -> str:
        '''
            获取md文件的内容
            :Args:
                - mdfile: md文件路径
            :Return:
                - md文件内容
        '''
        mdsrc = ''
        md_cont = ''
        if self.md_file.startswith('http'):
            _mc = minioclient()
            mdsrc = self.md_file.split('/static/')[-1]
            md_cont = _mc.get_file_cont(mdsrc)
        else:
            with open(self.md_file, 'r', encoding='utf-8') as f:
                md_cont = f.read()

        return md_cont
    
    # 使用正则表达式，获取md文件的目录结构和各个章节下面的内容
    def get_md_toc_content(self) -> list:
        '''
            使用正则表达式，解析md文件的目录结构和各个章节下面的内容，返回一个列表
            例如：
                mdcont = '
                    # 标题1-1
                        内容1-1
                    ## 标题1-1-2-1
                        内容2-1
                    ## 标题1-1-2-2
                        内容2-2
                        ### 标题3-1
                            内容3-1
                    ## 标题1-1-2-3
                        内容2-3
                    # 标题1-2
                        内容1-2
                    ## 标题1-2-2-1
                        内容1-2-2-1
                    ## 标题1-2-2-2
                        内容1-2-2-2
                        ### 标题1-2-2-2-3
                            内容1-2-2-2-3
                    ## 标题1-2-2-3
                '
            :Args:
                - 无
            :Return:
                - 返回一个列表，例如：
                [
                    {
                        'h1': '标题1-1',
                        'content': '内容1',
                        'sub': [
                            {
                                'h2': '标题1-1-2-1',
                                'content': '内容2-1',
                                'sub': [
                                    {
                                    'h3': '标题3-1',
                                    'content': '内容3-1'
                                    }
                                ]
                            },
                            {
                                'h2': '标题1-1-2-2',
                                'content': '内容2-2',
                                'sub': []
                                },
                            {
                            ...
                            
                        ]
                    },
                    {
                        'h1': '标题1-2',
                        'content': '内容1-2',
                        'sub': [
                            {
                                'h2': '标题1-2-2-1',
                                'content': '内容1-2-2-1',
                                'sub': []
                            },
                            {
                                'h2': '标题1-2-2-2',
                                'content': '内容1-2-2-2',
                                'sub': [
                                    {
                                        'h3': '标题1-2-2-2-3',
                                        'content': '内容1-2-2-2-3'
                                    }
                                ]
                            },
                            {
                            ...
                        ]
                    }
                ]
        '''
        md_content = self.md_cont
        # 定义正则表达式模式
        pattern = re.compile(r'^(#{1,6})\s+(.*)', re.MULTILINE)

        # 初始化结果列表和当前层级的堆栈
        result = []
        stack = []

        # 遍历匹配的标题
        for match in pattern.finditer(md_content):
            level = len(match.group(1))  # 标题级别
            title = match.group(2)  # 标题内容
            content_start = match.end()  # 内容开始位置

            # 查找下一个标题的位置
            next_match = pattern.search(md_content, content_start)
            content_end = next_match.start() if next_match else len(md_content)
            content = md_content[content_start:content_end].strip()

            # 创建当前标题的字典
            current = {
                f'h{level}': title,
                'content': content,
                'sub': []
            }

            # 根据标题级别更新堆栈
            if level == 1:
                result.append(current)
                stack = [current]
            else:
                while len(stack) >= level:
                    stack.pop()
                stack[-1]['sub'].append(current)
                stack.append(current)

        return result
    
    # get_md_toc_content

    def get_md_toc(self, toc_content:list=None) -> list:
        '''
            获取md文件的目录结构，返回一个树形结构的字典
            将self.md_toc_cont 返回的列表转换为树形结构，其实是递归的算法去掉列表中所有元素的content字段即可
            self.md_toc_cont 的结构如下：
                [
                    {
                        'h1': '标题1-1',
                        'content': '内容1',
                        'sub': [
                            {
                                'h2': '标题1-1-2-1',
                                'content': '内容2-1',
                                'sub': [
                                    {
                                    'h3': '标题3-1',
                                    'content': '内容3-1'
                                    }
                                ]
                            },
                            {
                                'h2': '标题1-1-2-2',
                                'content': '内容2-2',
                                'sub': []
                                },
                            {
                            ...
                            
                        ]
                    },
                    {
                        'h1': '标题1-2',
                        'content': '内容1-2',
                        'sub': [
                            {
                                'h2': '标题1-2-2-1',
                                'content': '内容1-2-2-1',
                                'sub': []
                            },
                            {
                                'h2': '标题1-2-2-2',
                                'content': '内容1-2-2-2',
                                'sub': [
                                    {
                                        'h3': '标题1-2-2-2-3',
                                        'content': '内容1-2-2-2-3'
                                    }
                                ]
                            },
                            {
                            ...
                        ]
                    }
                ]
            :Args:
                - var: 描述
            :Return:
        '''
        if toc_content is None:
            toc_content = self.md_toc_cont
        
        def remove_content(item):
            # 创建一个新的字典，去掉content字段
            new_item = {k: v for k, v in item.items() if k != 'content'}
            # 递归处理子项
            if 'sub' in new_item:
                new_item['sub'] = [remove_content(sub_item) for sub_item in new_item['sub']]
            return new_item

        # 处理整个列表
        return [remove_content(item) for item in toc_content]
    
    # get_md_toc

    # 获取md文件的主标题（第一个 # 标题1）
    def get_h1_title_lst(self) -> list:
        '''
            获取md文件的主标题（第一个 # 标题1）
            :Args:
                - 无
            :Return:
                - 列表，例如：['一级标题1', '一级标题2', '一级标题3']
        '''
        h1lst = []

        for toc in self.md_toc:
            h1lst.append(toc['h1'])
        
        return h1lst
        
    # 获取md文件的所有二级标题（## 标题2），返回一个列表
    def get_h2_title_lst(self, h1index:int=0) -> list:
        '''
            获取md文件的二级标题（## 标题2），返回一个字典
            :Args:
                - 无
            :Return:
                - 列表
                ['二级标题1', '二级标题2', '二级标题3']
                
        '''
        mdsubtitle = []
        for toc in self.md_toc[h1index]['sub']:
            mdsubtitle.append(toc['h2'])

        return h1index, mdsubtitle
        
    def get_image_lst(self, cont:str=None) -> list:
        '''
            使用正则表达式从内容中提取其中的图片，形成图片的URL列表
            :Args:
                - cont: Md内容字符串
            :Return:
                列表，比如：
                [
                    ["image-20241206094644597", "https://aliyuncs.com/image-20241206094644597.png"],
                    ["image-202412060946sewer", "https://aliyuncs.com/image-20241202221.png"]
                ]
        '''
        if cont is None:
            cont = self.md_cont
        # 定义正则表达式模式
        pattern = re.compile(r'!\[([^\]]+)\]\((https?://[^\)]+)\)')

        # 使用正则表达式查找所有匹配项
        matches = pattern.findall(cont)

        # 返回匹配结果
        return matches
    
    # get_image_lst

    def get_subtitle_by_title(self, titlestr:str) -> list:
        '''
            使用正则表达式中提取 [副标题]，返回str
            :Args:
                - titlestr: 标题
            :Return:
                返回副标题
        '''
        _sub = 'no'
        # 定义正则表达式模式
        pattern = re.compile(r'\[([^\]]+)\]')

        # 使用正则表达式查找所有匹配项
        matches = pattern.findall(titlestr)

        if len(matches)>0 :
            _sub = matches[0]

        # 返回匹配结果
        return _sub
    
    # func
    
    def md_slip_page(self, h1index:int=0) -> list:
        '''
            分页处理md文件的内容，返回一个list
            md文件分页逻辑：
                - 封面页，使用h1的内容+h1下面的h2 title列表
                - 第一个h2页面
                - 第二个h2页面
                ...
            :Args:
                - h1index: 文章主标题序号，从0开始
            :Return:
                [
                    {
                        'page': 1,
                        'pagename': '封面',
                        'title': '一级标题1', # 对应h1, 一个md文件一般只有一个h1
                        'subtitle': '副标题1', # 对应h1 title中的[副标题]
                        'sublist': [], # 对应h2 title列表
                        'content': ['内容1',['img1', 'img2']] # 对应h1下的内容,并从内容中提取图片列表
                    },
                    {
                        'page': 2,
                        'pagename': '第一个h2标题',
                        'title': '二级标题2', # 对应h2
                        'subtitle': '副标题2', # 对应h2 title中的[副标题]
                        'sublist': [['h3title','h3内容',['img1','img2']], ....], 对应h3 title列表
                        'content': ['内容1',['img1', 'img2',....]] # 对应h2下的内容,并从内容中提取图片列表
                    },
                    ...
                ]
        '''
        _page_lst = []
        _h2lst = self.get_h2_title_lst()[1]
        _cov_p = {
            'page':1,
            'pagename': 'cover',
            'title': self.md_toc_cont[h1index]['h1'],
            'subtitle': self.get_subtitle_by_title(self.md_toc_cont[h1index]['h1']),
            'sublist': self.get_h2_title_lst(),
            'content': [self.md_toc_cont[h1index]['content'], self.get_image_lst(self.md_toc_cont[h1index]['content'])]
        }
        _page_lst.append(_cov_p)

        for h2t in _h2lst:
            _i = _h2lst.index(h2t)
            _idx = _i+2
            print("h2标题", h2t)
            _h2page = {
                        'page': _idx,
                        'pagename': 'page'+str(_idx),
                        'title': h2t, # 对应h2
                        'subtitle': self.get_subtitle_by_title(h2t), # 对应h2 title中的[副标题]
                        'sublist': self.get_h3_title_cont(h1index,_i), # 对应h3 title列表
                        'content': self.get_h2_title_cont(h1index,_i) # 对应h2下的内容,并从内容中提取图片列表
                    }
            _page_lst.append(_h2page)

        
        return _page_lst
    
    # func

    # 获取md文件的一级标题（# 标题1），和标题下的内容（ 截止到第一个标题2 ## ），返回一个字典
    def get_h1_title_cont(self, h1index:int=0) -> dict:
        '''
            获取md文件的一级标题（# 标题1），和标题下的内容（ 截止到第一个标题2 ## ），返回一个字典
            字典格式：{'title': '标题', 'content': '内容'}
            :Args:
                - h1index: 标题1的索引，从0开始
            :Return:
                - 字典,例如：{'title': '标题', 'content': ['内容',['img1','img2']]}
        '''
        _h1_title = self.md_toc_cont[h1index]['h1']
        _h1_cont = self.md_toc_cont[h1index]['content']
        _h1_imglst = self.get_image_lst(_h1_cont)
        _h1_dict = {'title': _h1_title, 'content': [_h1_cont, _h1_imglst]}
        return _h1_dict
    
    # get_main_title_cont

    # 获取md文件的二级标题（## 标题2），返回一个列表
    def get_h2_title_cont(self, h1index:int=0, h2index:int=0) -> list:
        '''
            获取md文件的二级标题（## 标题2），返回一个列表
            
        '''
        _h2_cont = self.md_toc_cont[h1index]['sub'][h2index]['content']
        _h2_imglst = self.get_image_lst(_h2_cont)
        _h2_lst = [_h2_cont,_h2_imglst]
        return _h2_lst
    
    # get_h2_title_cont

    # 获取md文件的三级标题（### 标题3），和标题下的内容（ 截止到第一个标题4 ####， 如果这个标题3下不存在标题4，则截止到下一个标题3 ），返回一个列表
    def get_h3_title_cont(self, h1index:int=0, h2index:int=0) -> list:
        '''
            获取md文件的三级标题，返回一个列表
            :Args:
                - h2index: 标题2的索引，从0开始
                - h3index: 标题3的索引，从0开始
            :Return:
                返回 [['h3title','h3内容',['img1','img2']], ....]
        '''
        _h2_sub = self.md_toc_cont[h1index]['sub'][h2index]['sub']
        _h3_lst = []

        for h3item in _h2_sub:
            _h3_title = h3item['h3']
            _h3_cont = h3item['content']
            _h3_imglst = self.get_image_lst(_h3_cont)
            _h3_lst.append([_h3_title,_h3_cont,_h3_imglst])

        return _h3_lst
    
    # get_h3_title_cont

